#ifndef JOINING_THREAD_H
#define JOINING_THREAD_H
#include <thread>

/**
 * @brief 模仿jthread
 */
class joining_thread
{
public:
    joining_thread() = default;

    /**
     * @brief 构造一个 joining_thread 对象，并传递可调用对象和参数
     * @tparam Callable 可调用对象类型
     * @tparam Args 可调用对象参数类型
     * @param f 线程函数
     * @param args 线程函数参数
     */
    template<class Callable, class... Args>
    explicit joining_thread(Callable&& f , Args&&... args)
        : _t(std::forward<Callable>(f), std::forward<Args>(args)...)
    {}

    /**
     * @brief 转移线程所有权
     * @param t 线程对象
     */
    explicit joining_thread(std::thread t) noexcept
        : _t(std::move(t))
    {}

    /**
     * @brief 转移线程所有权
     * @param other joining_thread 对象
     */
    joining_thread(joining_thread&& other) noexcept
        : _t(std::move(other._t))
    {}

    /**
     * @brief 赋值操作符，转移线程所有权
     * @param other joining_thread 对象
     * @return joining_thread&
     */
    joining_thread& operator = (joining_thread&& other) noexcept
    {
        if (_t.joinable())
        {
            _t.join();
        }
        _t = std::move(other._t); // 转移线程所有权
        return *this;
    }

    /**
     * @brief 赋值操作符，转移线程所有权
     * @param t joining_thread 对象
     * @return joining_thread&
     */
    joining_thread& operator = (std::thread t) noexcept
    {
        if (_t.joinable())
        {
            _t.join();
        }
        _t = std::move(t); // 转移线程所有权
        return *this;
    }

    /**
     * @brief 析构函数，如果线程没有被 join 或 detach，则在析构函数中等待线程完成
     */
    ~joining_thread()
    {
        if (_t.joinable())
        {
            _t.join(); // 等待线程完成
        }
    }

public:
    /**
     * @brief 交换两个 joining_thread 对象的线程
     * @param other joining_thread 对象
     */
    void swap(joining_thread& other) noexcept
    {
        _t.swap(other._t);
    }

    /**
     * @brief 获取线程id
     * @return 线程id
     */
    auto get_id() const noexcept
    {
        return _t.get_id();
    }

    /**
     * @brief 检擦看线程是否可连接
     * @return 线程是否可连接
     */
    auto joinable() const noexcept
    {
        return _t.joinable();
    }

    /**
     * @brief 等待线程完成
     */
    void join()
    {
        _t.join();
    }

    /**
     * @brief 分离线程
     */
    void detach()
    {
        _t.detach();
    }

private:
    std::thread _t;
};
#endif //JOINING_THREAD_H
